第 1 课:张量操作
在 PyTorch 中, torch.Tensor 是存储和变换数据的主要工具。
Tensor 和NumPy的多维数组非常类似。然而,Tensor 提供GPU计算和自动求梯度等更多功能,
我们通常将数据以张量的形式进行表示,比如我们用三维张量表示一个RGB图像,四维张量表示视频。
我们可以将标量视为零阶张量,矢量可以视为一阶张量,矩阵就是二阶张量。
| 张量维度 | 代表含义 |
|---|---|
| 0维张量 | 代表的是标量(数字) |
| 1维张量 | 代表的是向量 |
| 2维张量 | 代表的是矩阵 |
| 3维张量 | 时间序列数据 股价 文本数据 单张彩色图片(RGB) |
注意:通常我们调用 torch.tensor 进行创建张量,不是调用 torch.Tensor 类
torch.Tensor 是Python的一个类, torch.tensor 是一个函数。
Tensor主要有以下八个主要属性,data,dtype,shape,device,grad,grad_fn,is_leaf,requires_grad。
-
data:多维数组,最核心的属性,其他属性都是为其服务的; -
dtype:多维数组的数据类型 -
shape:多维数组的形状 -
device: tensor所在的设备,cpu或cuda; -
grad,grad_fn,is_leaf,requires_grad: 用于梯度计算
张量的属性还有很多,大家可以通过Pycharm的debug功能进行查看
(一) 创建张量
常见的构造Tensor的方法:
| 函数 | 功能 |
|---|---|
| tensor(data) | 类似于np.array |
| ones(sizes) | 全1 |
| zeros(sizes) | 全0 |
| eye(sizes) | 对角为1,其余为0 |
| arange(s,e,step) | 从s到e,步长为step |
| linspace(s,e,steps) | 从s到e,均匀分成step份 |
| rand/randn(sizes) | rand是[0,1)均匀分布;randn是服从N(0,1)的正态分布 |
| normal(mean,std) | 正态分布(均值为mean,标准差是std) |
| randperm(m) | 随机排列 |
1. 直接构建张量
标准格式如下:
torch.tensor(data, dtype=None, device=None, requires_grad=False, pin_memory=False)
-
data(array_like)tensor的初始数据,可以是list, tuple, numpy array, scalar或其他类型。 -
dtype(torch.dtype, optional)tensor的数据类型,如torch.uint8, torch.float, torch.long等 -
device (torch.device, optional)决定tensor位于cpu还是gpu。默认为 cpu。 -
requires_grad (bool, optional)决定是否需要计算梯度。 -
pin_memory (bool, optional)是否将tensor存于锁页内存。这与内存的存储方式有关,通常为False。
import torch
import numpy as np
t_from_list = torch.tensor( [[1., -1.], [1., -1.]] )
t_from_array= torch.tensor( np.array([[1, -1], [1,-1]]))
print(t_from_list, t_from_list.dtype)
print(t_from_array, t_from_array.dtype)
tensor([[ 1., -1.],
[ 1., -1.]]) torch.float32
tensor([[ 1, -1],
[ 1, -1]]) torch.int64
2. 创建全零张量
标准格式如下:
torch.zeros(*size, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
-
layout(torch.layout, optional)- 张量在内存中采用何种布局方式,如torch.strided, torch.sparse_coo等。 -
out(tensor, optional)- 输出的tensor,即该函数返回的tensor可以通过out进行赋值
import torch
o_t = torch.tensor([1])
t = torch.zeros((3, 3), out=o_t)
print(t)
print(o_t)
print(id(t), id(o_t))
# 可以看到,通过torch.zeros创建的张量不仅赋给了t,同时赋给了o_t,并且这两个张量是共享同一块内存,只是变量名不同。
tensor([[0, 0, 0],
[0, 0, 0],
[0, 0, 0]])
tensor([[0, 0, 0],
[0, 0, 0],
[0, 0, 0]])
140209880685520 140209880685520
创建全一矩阵和其他矩阵的方法相同
torch.ones(size, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
torch.full(size, fill_value, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
3. 创建等差的1维张量
标准格式如下:
torch.arange(start=0, end, step=1, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
张量长度为 (end-start)/step,需要注意数值区间为[start, end)。 主要参数:
start (Number)– 数列起始值,默认值为0。the starting value for the set of points. Default: 0.end (Number)– 数列的结束值。step (Number)– 数列的等差值,默认值为1。out (Tensor, optional)– 输出的tensor,即该函数返回的tensor可以通过out进行赋值。
import torch
print(torch.arange(1, 2.51, 0.5))
tensor([1.0000, 1.5000, 2.0000, 2.5000])
4. 创建均分的1维张量
标准格式如下
torch.linspace(start, end, steps=100, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
张量长度为steps,区间为[start, end]。
主要参数:
start (float)– 数列起始值。end (float)– 数列结束值。steps (int)– 数列长度。
print(torch.linspace(3, 10, steps=5))
print(torch.linspace(1, 5, steps=3))
tensor([ 3.0000, 4.7500, 6.5000, 8.2500, 10.0000])
tensor([1., 3., 5.])
5. 创建对数均分的1维张量
标准格式如下
torch.logspace(start, end, steps=100, base=10.0, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
张量长度为steps, 底为base。
主要参数:
-
start (float)– 确定数列起始值为base^start -
end (float)– 确定数列结束值为base^end -
steps (int)– 数列长度。 -
base (float)- 对数函数的底,默认值为10,此参数是在pytorch 1.0.1版本之后加入的。
torch.logspace(start=0.1, end=1.0, steps=5)
torch.logspace(start=2, end=2, steps=1, base=2)
tensor([4.])
6. 创建单位对角矩阵
标准格式如下
torch.eye(n, m=None, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)**
主要参数:
-
n (int)- 矩阵的行数 -
m (int, optional)- 矩阵的列数,默认值为n,即默认创建一个方阵
import torch
print(torch.eye(3))
print(torch.eye(3, 4))
tensor([[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.]])
tensor([[1., 0., 0., 0.],
[0., 1., 0., 0.],
[0., 0., 1., 0.]])
7. 创建“空”张量
标准格式如下:
torch.empty(*size, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False, pin_memory=False)
这里的“空”指的是不会进行初始化赋值操作。
主要参数:
-
size (int...)- 张量维度 -
pin_memory (bool, optional)- pinned memory 又称page locked memory,即锁页内存,该参数用来指示是否将tensor存于锁页内存,通常为False,若内存足够大,建议设置为True,这样在转到GPU时会快一些。
8. 创建“空”张量
标准格式如下
torch.empty_strided(size, stride, dtype=None, layout=None, device=None, requires_grad=False, pin_memory=False)
这里的“空”指的是不会进行初始化赋值操作。
主要参数:
-
stride (tuple of python:ints)- 张量存储在内存中的步长,是设置在内存中的存储方式。 -
size (int...)- 张量维度 -
pin_memory (bool, optional)- 是否存于锁页内存。
9. 高斯分布生成随机数
标准格式如下
torch.normal(mean, std, out=None)
主要参数:
-
mean (Tensor or Float)- 高斯分布的均值, -
std (Tensor or Float)- 高斯分布的标准差
特别注意事项: mean和std的取值分别有2种,共4种组合,不同组合产生的效果也不同,需要注意
-
mean为张量,std为张量,torch.normal(mean, std, out=None),每个元素从不同的高斯分布采样,分布的均值和标准差由mean和std对应位置元素的值确定;
-
mean为张量,std为标量,torch.normal(mean, std=1.0, out=None),每个元素采用相同的标准差,不同的均值;
-
mean为标量,std为张量,torch.normal(mean=0.0, std, out=None), 每个元素采用相同均值,不同标准差;
-
mean为标量,std为标量,torch.normal(mean, std, size, *, out=None) ,从一个高斯分布中生成大小为size的张量;
import torch
mean = torch.arange(1, 11.)
std = torch.arange(1, 0, -0.1)
normal = torch.normal(mean=mean, std=std)
print("mean: {}, \nstd: {}, \nnormal: {}".format(mean, std, normal))
# 1.3530是通过均值为1,标准差为1的高斯分布采样得来,
# -1.3498是通过均值为2,标准差为0.9的高斯分布采样得来,以此类推
mean: tensor([ 1., 2., 3., 4., 5., 6., 7., 8., 9., 10.]),
std: tensor([1.0000, 0.9000, 0.8000, 0.7000, 0.6000, 0.5000, 0.4000, 0.3000, 0.2000,
0.1000]),
normal: tensor([ 0.5680, 0.8779, 4.1467, 3.7689, 4.7406, 6.2640, 7.2629, 8.2965,
9.0057, 10.0525])
10. 生成均匀分布
标准格式如下:
torch.rand(*size, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
主要参数:
size (int...)- 创建的张量的形状
基于已经存在的 tensor,创建一个 tensor
x = x.new_ones(4, 3, dtype=torch.double)
# 等效于 x = torch.ones(4, 3, dtype=torch.double)
print(x)
x = torch.randn_like(x, dtype=torch.float) # 重置数据类型为随机张量
print(x)